// @ts-nocheck
import { NO_INTERCEPT } from './types'

/**
 * 使用方式：
 * RequestInterceptor.getInstance().initialize((url) => {
 *   return url.split('/api/v1/oec/affiliate/creator/marketplace/find').length > 1
 * }).onBeforeSend(async (request) => {
 *   if (oecSellerId.value) return true
 *
 *   const url = new URL(request.url)
 *   oecSellerId.value = url.searchParams.get('oec_seller_id')
 *
 *   if (oecSellerId.value) {
 *     console.log('找到 oec_seller_id:', oecSellerId)
 *   }
 * })
 */

// HTTP 方法类型
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS'

// 请求数据类型
interface RequestData {
  id: string
  type: 'fetch'
  method: HttpMethod
  url: string
  headers: Record<string, string>
  response: string
  body?: any
  timestamp: number
  originalInput: string | Request
  originalInit: RequestInit
}

export class $RequestInterceptor {
  // 单例实例
  static instance = null

  // 获取单例实例
  static getInstance() {
    if (!$RequestInterceptor.instance) {
      $RequestInterceptor.instance = new $RequestInterceptor()
    }
    return $RequestInterceptor.instance
  }

  constructor() {
    this.isInitialized = false
    this.requestStore = []
    this.callbacks = {
      beforeSend: [],
      afterResponse: []
    }
    this.urlPatterns = null
  }

  // 初始化拦截器
  initialize(urlPatterns = () => true) {
    if (this.isInitialized) {
      console.warn('RequestInterceptor 已经初始化过了')
      return this
    }

    if (typeof urlPatterns !== 'function') {
      throw new Error('initialize 方法需要传入一个函数参数作为 URL 匹配条件')
    }

    this.urlPatterns = urlPatterns
    this.isInitialized = true

    // 保存原始方法
    this.originalMethods = {
      xhr: {
        open: XMLHttpRequest.prototype.open,
        send: XMLHttpRequest.prototype.send,
        setRequestHeader: XMLHttpRequest.prototype.setRequestHeader
      },
      fetch: unsafeWindow.fetch.bind(unsafeWindow)
    }

    // 初始化拦截器
    this.initializeXHRInterceptor()
    this.initializeFetchInterceptor()

    return this
  }

  // XHR拦截器初始化
  initializeXHRInterceptor() {
    const self = this

    // 存储请求头
    XMLHttpRequest.prototype._requestHeaders = {}

    // 劫持setRequestHeader
    XMLHttpRequest.prototype.setRequestHeader = function (header, value) {
      this._requestHeaders[header] = value
      return self.originalMethods.xhr.setRequestHeader.call(this, header, value)
    }

    // 劫持open方法
    XMLHttpRequest.prototype.open = function (method, url) {
      this._method = method
      this._url = url
      return self.originalMethods.xhr.open.call(this, method, url)
    }

    // 劫持send方法
    XMLHttpRequest.prototype.send = function (body) {
      const shouldIntercept = self.urlPatterns(String(this._url))
      const requestId = 'xhr_' + Date.now() + Math.random().toString(36).substr(2, 9)

      // 处理请求体，转换为JSON格式
      let jsonBody = null
      try {
        if (body) {
          if (typeof body === 'string') {
            // 尝试解析JSON字符串
            try {
              jsonBody = JSON.parse(body)
            } catch {
              jsonBody = body // 如果不是JSON，保持原样
            }
          } else if (body instanceof FormData) {
            // 处理FormData
            const formDataObj = {}
            for (let [key, value] of body.entries()) {
              formDataObj[key] = value
            }
            jsonBody = formDataObj
          } else if (body instanceof Blob) {
            // 处理Blob对象
            jsonBody = {
              _type: 'Blob',
              size: body.size,
              type: body.type
            }
          } else if (body instanceof ArrayBuffer) {
            // 处理ArrayBuffer
            jsonBody = {
              _type: 'ArrayBuffer',
              byteLength: body.byteLength
            }
          } else {
            // 其他类型直接使用
            jsonBody = body
          }
        }
      } catch (error) {
        console.warn('处理XHR请求体失败:', error)
        jsonBody = '[处理失败]'
      }

      const requestData = {
        id: requestId,
        type: 'xhr',
        method: this._method,
        url: this._url,
        headers: { ...this._requestHeaders },
        body: jsonBody, // 使用处理后的JSON格式body
        rawBody: body, // 保留原始body用于调试
        timestamp: Date.now(),
        xhr: this
      }

      if (shouldIntercept) {
        self.requestStore.push(requestData)

        self.triggerCallbacks('beforeSend', requestData)
      }

      // 添加响应监听
      this.addEventListener('load', function () {
        if (this.readyState === 4) {
          // 处理响应数据
          let responseBody = this.response
          try {
            if (typeof responseBody === 'string') {
              try {
                responseBody = JSON.parse(responseBody)
              } catch {
                // 保持原样，不是JSON
              }
            }
          } catch (error) {
            console.warn('处理XHR响应体失败:', error)
          }

          const responseData = {
            requestId: requestId,
            status: this.status,
            response: responseBody,
            headers: this.getAllResponseHeaders(),
            timestamp: Date.now()
          }

          if (shouldIntercept) {
            // 创建完整的请求响应数据
            const completeData = {
              ...requestData,
              ...responseData,
              type: 'xhr'
            }

            // 触发响应后回调 - 传递JSON数据
            self.triggerCallbacks('afterResponse', completeData)
          }
        }
      })

      this.addEventListener('error', function () {
        const errorData = {
          requestId: requestId,
          request: requestData,
          error: 'XHR request failed',
          timestamp: Date.now(),
          type: 'xhr'
        }

        if (shouldIntercept) {
          self.triggerCallbacks('onError', errorData)
        }
      })

      return self.originalMethods.xhr.send.call(this, body)
    }
  }

  // Fetch拦截器初始化
  initializeFetchInterceptor() {
    const self = this

    unsafeWindow.fetch = async function (input, init = {}) {
      // 检查是否有 Symbol 标记
      const hasNoInterceptMark = init && init[NO_INTERCEPT] !== undefined
      const skipCallbacks = hasNoInterceptMark && init[NO_INTERCEPT]

      // 创建清理后的 init（始终删除标记）
      const cleanInit = { ...init }
      if (hasNoInterceptMark) {
        delete cleanInit[NO_INTERCEPT]
      }

      const url = typeof input === 'string' ? input : input.url

      let method = 'GET'
      if (init.method) {
        method = init.method.toUpperCase()
      } else if (input instanceof Request && input.method) {
        method = input.method.toUpperCase()
      }

      const headers = new Headers(init.headers || {})
      const headersObj = {}
      headers.forEach((value, key) => {
        headersObj[key] = value
      })

      const shouldIntercept = self.urlPatterns(String(url))
      const requestId = 'fetch_' + Date.now() + Math.random().toString(36).substr(2, 9)

      // 关键修改：正确处理 Request 对象的 body
      let requestBody = null
      let bodyData = null

      try {
        // 方法1：如果 input 是 Request 对象，尝试克隆并读取
        if (input instanceof Request) {
          const requestClone = input.clone()
          requestBody = requestClone.body

          if (requestBody) {
            // 尝试读取 Request 的 body
            const text = await requestClone.text()
            try {
              bodyData = JSON.parse(text)
            } catch {
              bodyData = text
            }
          }
        }

        // 方法2：如果 init 中有 body
        if (!bodyData && init.body) {
          requestBody = init.body

          if (typeof init.body === 'string') {
            try {
              bodyData = JSON.parse(init.body)
            } catch {
              bodyData = init.body
            }
          } else {
            bodyData = init.body
          }
        }

        // 方法3：如果以上都失败，尝试从原始请求中提取
        if (!bodyData) {
          // 对于 POST 请求，通常应该有 body
          if (method === 'POST') {
            bodyData = '[POST请求体 - 需要进一步调试]'
          }
        }
      } catch (error) {
        console.warn('读取请求体失败:', error)
        bodyData = '[读取失败]'
      }

      const requestData = {
        id: requestId,
        type: 'fetch',
        method: method,
        url: url,
        headers: headersObj,
        body: bodyData,
        rawRequestBody: requestBody,
        timestamp: Date.now(),
        originalInput: input,
        originalInit: { ...init }
      }

      if (skipCallbacks) {
        console.log('跳过自己发送的回调函数')
      }

      if (shouldIntercept && !skipCallbacks) {
        self.requestStore.push(requestData)
        self.triggerCallbacks('beforeSend', requestData)
      }

      // 执行原始请求
      return self.originalMethods.fetch(input, init).then(response => {
        const responseClone = response.clone()
        return responseClone.text().then(responseText => {
          const responseData = {
            requestId: requestId,
            status: response.status,
            statusText: response.statusText,
            response: responseText,
            headers: Object.fromEntries(response.headers.entries()),
            timestamp: Date.now()
          }

          if (shouldIntercept && !skipCallbacks) {
            self.triggerCallbacks('afterResponse', {
              ...requestData,
              ...responseData,
              type: 'fetch'
            })
          }

          return response
        })
      }).catch(error => {
        console.error('Fetch 请求失败:', error, input, init)
        throw error
      })
    }
  }

  triggerCallbacks(type, data) {
    this.callbacks[type].forEach(callback => {
      try {
        callback(data)
      } catch (error) {
        console.error(`执行 ${type} 回调时出错:`, error)
      }
    })
  }

  onBeforeSend(callback) {
    if (!this.isInitialized) {
      throw new Error('请先调用 initialize() 方法初始化拦截器')
    }
    this.callbacks.beforeSend.push(callback)
    return this
  }

  onAfterResponse(callback) {
    if (!this.isInitialized) {
      throw new Error('请先调用 initialize() 方法初始化拦截器')
    }
    this.callbacks.afterResponse.push(callback)
    return this
  }

  getRequests() {
    return [...this.requestStore]
  }

  getXHRRequests() {
    return this.requestStore.filter(req => req.type === 'xhr')
  }

  getFetchRequests() {
    return this.requestStore.filter(req => req.type === 'fetch')
  }

  clearRequests() {
    this.requestStore = []
  }

  resend(request, modifications = {}) {
    if (request.type === 'xhr') {
      return this.resendXHR(request, modifications)
    } else if (request.type === 'fetch') {
      return this.resendFetch(request, modifications)
    }
    return Promise.reject(new Error('Unknown request type'))
  }

  resendXHR(request, modifications = {}) {
    return new Promise((resolve, reject) => {
      const xhr = new XMLHttpRequest()
      const finalUrl = modifications.url || request.url
      const finalMethod = modifications.method || request.method
      const finalHeaders = { ...request.headers, ...(modifications.headers || {}) }
      let finalBody = request.body

      if (modifications.body) {
        try {
          const parsedBody = typeof request.body === 'string' ?
            JSON.parse(request.body) : request.body
          finalBody = JSON.stringify({ ...parsedBody, ...modifications.body })
        } catch {
          finalBody = modifications.body
        }
      }

      xhr.open(finalMethod, finalUrl)

      Object.entries(finalHeaders).forEach(([key, value]) => {
        xhr.setRequestHeader(key, value)
      })

      xhr.onload = () => resolve({
        type: 'xhr',
        status: xhr.status,
        response: xhr.response,
        headers: xhr.getAllResponseHeaders()
      })

      xhr.onerror = reject
      xhr.send(finalBody)
    })
  }

  resendFetch(request, modifications = {}) {
    const finalUrl = modifications.url || request.url
    const finalMethod = modifications.method || request.method
    const finalHeaders = { ...request.headers, ...(modifications.headers || {}) }
    let finalBody = request.body

    if (modifications.body) {
      try {
        const parsedBody = typeof request.body === 'string' ?
          JSON.parse(request.body) : request.body
        finalBody = JSON.stringify({ ...parsedBody, ...modifications.body })
      } catch {
        finalBody = modifications.body
      }
    }

    const init = {
      method: finalMethod,
      headers: finalHeaders,
      body: finalBody
    }

    // 移除undefined值
    Object.keys(init).forEach(key => init[key] === undefined && delete init[key])

    return fetch(finalUrl, init).then(response => {
      return response.text().then(responseText => ({
        type: 'fetch',
        status: response.status,
        statusText: response.statusText,
        response: responseText,
        headers: Object.fromEntries(response.headers.entries())
      }))
    })
  }

  // 恢复原始方法
  restore() {
    // 恢复XHR方法
    XMLHttpRequest.prototype.open = this.originalMethods.xhr.open
    XMLHttpRequest.prototype.send = this.originalMethods.xhr.send
    XMLHttpRequest.prototype.setRequestHeader = this.originalMethods.xhr.setRequestHeader
    delete XMLHttpRequest.prototype._requestHeaders

    // 恢复fetch方法
    unsafeWindow.fetch = this.originalMethods.fetch

    this.isInitialized = false
  }

  // 单独恢复XHR
  restoreXHR() {
    XMLHttpRequest.prototype.open = this.originalMethods.xhr.open
    XMLHttpRequest.prototype.send = this.originalMethods.xhr.send
    XMLHttpRequest.prototype.setRequestHeader = this.originalMethods.xhr.setRequestHeader
    delete XMLHttpRequest.prototype._requestHeaders
  }

  // 单独恢复Fetch
  restoreFetch() {
    unsafeWindow.fetch = this.originalMethods.fetch
  }
}